package com.echo.echovividlive.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.echo.echovividlive.common.UserThread;
import com.echo.echovividlive.domain.dto.PageQueryDTO;
import com.echo.echovividlive.domain.entity.Result;
import com.echo.echovividlive.domain.entity.User;
import com.echo.echovividlive.domain.entity.UserInteract;
import com.echo.echovividlive.domain.entity.Video;
import com.echo.echovividlive.domain.vo.FollowingPageVO;
import com.echo.echovividlive.domain.vo.PageVO;
import com.echo.echovividlive.mapper.UserInteractMapper;
import com.echo.echovividlive.mapper.UserMapper;
import com.echo.echovividlive.mapper.VideoMapper;
import com.echo.echovividlive.service.IUserInteractService;
import com.github.pagehelper.PageHelper;
import lombok.RequiredArgsConstructor;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.stream.Collectors;

import static com.echo.echovividlive.common.Constants.*;

@Service
@RequiredArgsConstructor
public class UserInteractServiceImpl extends ServiceImpl<UserInteractMapper,UserInteract> implements IUserInteractService {

    private final StringRedisTemplate stringRedisTemplate;

    private final UserMapper userMapper;

    private final RabbitTemplate rabbitTemplate;

    private final VideoMapper videoMapper;

    private final UserInteractMapper userInteractMapper;
    @Override
    @Transactional
    public Result following(Integer userId) {
        Integer currentUserId = UserThread.getUserId();
        // 检查是否关注了
        if(checkUserFollowing(currentUserId, userId)) {
            // 取关
            userMapper.update(new LambdaUpdateWrapper<User>()
                    .eq(User::getUserId,userId)
                    .setSql("fans_count = fans_count - 1"));
            userMapper.update(new LambdaUpdateWrapper<User>()
                    .eq(User::getUserId,currentUserId)
                    .setSql("following_count = following_count - 1"));
            stringRedisTemplate.opsForList().remove(USER_FANS_KEY+userId,1,currentUserId.toString());
            stringRedisTemplate.opsForList().remove(USER_FOLLOWING_KEY+currentUserId,1,userId.toString());
            return Result.success();
        }
        // 关注
        stringRedisTemplate.opsForList().leftPush(USER_FOLLOWING_KEY+currentUserId,userId.toString());
        stringRedisTemplate.opsForList().leftPush(USER_FANS_KEY+userId,currentUserId.toString());
        // 将当前用户的id放入队列，异步更新数据库
        rabbitTemplate.convertAndSend(USER_FOLLOWING_QUEUE,currentUserId.toString());
        rabbitTemplate.convertAndSend(USER_FANS_QUEUE,userId.toString());
        userMapper.update(new LambdaUpdateWrapper<User>()
                .eq(User::getUserId,userId)
                .setSql("fans_count = fans_count + 1"));
        userMapper.update(new LambdaUpdateWrapper<User>()
                .eq(User::getUserId,currentUserId)
                .setSql("following_count = following_count + 1"));
        return Result.success();
    }

    @Override
    @Transactional
    public Result like(Integer videoId) {
        Integer userId = UserThread.getUserId();
        Long index = stringRedisTemplate.opsForList().indexOf(USER_LIKE_KEY + userId, videoId.toString());
        if(index == null) {
            // 写入redis
            stringRedisTemplate.opsForList().leftPush(USER_LIKE_KEY+userId,videoId.toString());
            // 将当前用户的id放入队列，异步更新数据库
            rabbitTemplate.convertAndSend(USER_LIKE_QUEUE,userId.toString());
            videoMapper.update(new LambdaUpdateWrapper<Video>()
                    .eq(Video::getVideoId,videoId)
                    .setSql("good_count = good_count + 1"));
            return Result.success();
        }
        // 取消点赞
        stringRedisTemplate.opsForList().remove(USER_LIKE_KEY+userId,0,videoId.toString());
        // 将当前用户的id放入队列，异步更新数据库
        rabbitTemplate.convertAndSend(USER_LIKE_QUEUE,userId.toString());
        videoMapper.update(new LambdaUpdateWrapper<Video>()
                .eq(Video::getVideoId,videoId)
                .setSql("good_count = good_count - 1"));
        return Result.success();
    }

//    @Override
//    @Transactional
//    public Result cancelLike(Integer videoId) {
//        Integer userId = UserThread.getUserId();
//        // 写入redis
//        stringRedisTemplate.opsForList().remove(USER_LIKE_KEY+userId,1,videoId.toString());
//        // 将当前用户的id放入队列，异步更新数据库
//        rabbitTemplate.convertAndSend(USER_LIKE_QUEUE,userId.toString());
//        videoMapper.update(new LambdaUpdateWrapper<Video>()
//                .eq(Video::getVideoId,videoId)
//                .setSql("like_count = like_count - 1"));
//        return Result.success();
//    }

    @Override
    public Result checkFollowing(Integer userId) {
        Integer currentUserId = UserThread.getUserId();
        return Result.success(checkUserFollowing(currentUserId,userId));
    }

    @Override
    public Result getFollowingList(PageQueryDTO pageQueryDTO) {
        Integer userId = UserThread.getUserId();
        List<String> stringList = stringRedisTemplate.opsForList().range(USER_FOLLOWING_KEY + userId, 0, -1);
        if (stringList==null || stringList.isEmpty()){
            return Result.success(ListUtil.empty());
        }
        List<Integer> collect = stringList.stream().map((Integer::parseInt)).collect(Collectors.toList());
        PageHelper.startPage(pageQueryDTO.getPageIndex()==null?1:pageQueryDTO.getPageIndex()
                ,pageQueryDTO.getPageSize()==null?5:pageQueryDTO.getPageSize());
        List<User> users = userMapper.selectList(new LambdaQueryWrapper<User>().in(User::getUserId, collect));
        List<FollowingPageVO> res  = BeanUtil.copyToList(users, FollowingPageVO.class);
        return Result.success(res);
    }

    @Override
    public Result getFans(PageQueryDTO pageQueryDTO) {
        Integer userId = UserThread.getUserId();
        List<String> range = stringRedisTemplate.opsForList().range(USER_FANS_KEY + userId, 0, -1);
        if (range==null || range.isEmpty()){
            return Result.success(ListUtil.empty());
        }
        List<Integer> list = range.stream().map(Integer::parseInt).toList();
        PageHelper.startPage(pageQueryDTO.getPageIndex()==null?1:pageQueryDTO.getPageIndex()
                ,pageQueryDTO.getPageSize()==null?5:pageQueryDTO.getPageSize());
        List<User> users = userMapper.selectList(new LambdaQueryWrapper<User>().in(User::getUserId, list));
        List<FollowingPageVO> res  = BeanUtil.copyToList(users, FollowingPageVO.class);
        return Result.success(res);
    }

    private boolean checkUserFollowing(Integer fansId, Integer followingId) {
        Long index = stringRedisTemplate.opsForList().indexOf(USER_FOLLOWING_KEY + fansId, followingId.toString());
        return index!=null;
    }
}
